package com.tbit.uqbike.service.business.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tbit.common.enums.OperaPswEnum;
import com.tbit.uqbike.constant.BrandRemoteConfigConstant;
import com.tbit.uqbike.constant.OperaPswConstant;
import com.tbit.uqbike.constant.UserConstant;
import com.tbit.uqbike.enums.SystemCodeEnum;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.pojo.Account;
import com.tbit.uqbike.object.pojo.BrandRemoteConfig;
import com.tbit.uqbike.object.pojo.OperaPsw;
import com.tbit.uqbike.object.pojo.dto.OperaPswDTO;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.service.business.AccountService;
import com.tbit.uqbike.service.business.BrandRemoteConfigService;
import com.tbit.uqbike.service.business.OperaPswService;
import com.tbit.uqbike.webmanager.dao.core.OperaPswDao;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 操作密钥服务
 */
@Service
public class OperaPswServiceImpl implements OperaPswService {

    @Resource
    private OperaPswDao operaPswDao;
    @Resource
    private AccountService accountService;
    @Autowired
    private BrandRemoteConfigService brandRemoteConfigService;

    public Page<OperaPsw> queryPage(Integer brandId, Integer pageNo, Integer pageSize) {
        Account account = accountService.getById(brandId);
        if (Objects.isNull(account)) {
            throw new BaseException(SystemCodeEnum.BRAND_NOT_EXIST);
        }
        Page<OperaPsw> page = new Page<>(pageNo, pageSize);
        QueryWrapper<OperaPsw> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(OperaPsw::getBrandId, brandId)
                .select(OperaPsw.class, item -> !item.getProperty().equals("operaPsw"));
        Page<OperaPsw> operaPswPage = operaPswDao.selectPage(page, wrapper);
        if (operaPswPage.getTotal() == 0) {
            List<OperaPsw> operaPswList = initOperaPsw(brandId);
            operaPswPage.setRecords(operaPswList.stream().limit(10).collect(Collectors.toList()));
            operaPswPage.setTotal(pageSize);
        }
        return operaPswPage;
    }

    @Override
    public OperaPsw getByOperaPswId(Integer operaPswId) {
        return operaPswDao.selectById(operaPswId);
    }

    @Override
    public void updateByOperaPswId(OperaPswDTO operaPswDTO) {
        OperaPsw operaPsw = new OperaPsw();
        BeanUtils.copyProperties(operaPswDTO, operaPsw);
        if (Objects.nonNull(operaPswDTO.getNewOperaPsw())) {
            OperaPsw dbOperaPsw = operaPswDao.selectById(operaPswDTO.getOperaPswId());
            if (!Objects.equals(operaPswDTO.getOperaPsw(), dbOperaPsw.getOperaPsw())) {
                throw new BaseException(SystemCodeEnum.OPERA_PAW_ERROR);
            }
            operaPsw.setOperaPsw(operaPswDTO.getNewOperaPsw());
        }
        operaPswDao.updateById(operaPsw);
    }

    @Override
    public void checkOperaPsw(LoginInfo loginUser, Integer module, String operaPsw) {
        String dbOperaPsw;
        Boolean allOperaPswEnable = true;
        Boolean moduleOperaPswEnable = true;
        Integer type = loginUser.getType();
        /**系统管理员单独密码判断*/
        if (Objects.equals(type, UserConstant.USER_ADMIN)){
            if (operaPsw == null) {
                throw new BaseException(SystemCodeEnum.OPERA_PAW_ERROR);
            }
            dbOperaPsw = OperaPswConstant.ADMIN_OPERA_PSW;
        } else {
            BrandRemoteConfig brandRemoteConfig = brandRemoteConfigService.
                    getRemoteConfigByBrandIdAndConfigType(loginUser.getBrandId(), BrandRemoteConfigConstant.OPERA_PSW);
            OperaPsw operaPswByModule = getOperaPswByModule(loginUser.getBrandId(), module);
            allOperaPswEnable = Objects.equals(brandRemoteConfig.getParamKV(), "1");
            moduleOperaPswEnable = Objects.equals(operaPswByModule.getEnable(), 1);
            dbOperaPsw = operaPswByModule.getOperaPsw();
        }

        if (allOperaPswEnable && moduleOperaPswEnable){
            if (operaPsw == null){
                throw new BaseException(SystemCodeEnum.OPERA_PAW_ERROR);
            }
            if (!Objects.equals(dbOperaPsw, operaPsw)) {
                throw new BaseException(SystemCodeEnum.OPERA_PAW_ERROR);
            }
        }

    }

    @Override
    public OperaPsw getOperaPswByModule(Integer brandId, Integer module) {
        Account account = accountService.getById(brandId);
        if (Objects.isNull(account)) {
            throw new BaseException(SystemCodeEnum.BRAND_NOT_EXIST);
        }
        QueryWrapper<OperaPsw> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(OperaPsw::getBrandId, brandId)
                .eq(OperaPsw::getModule, module);
        OperaPsw operaPsw = operaPswDao.selectOne(wrapper);
        if (Objects.isNull(operaPsw)) {
            List<OperaPsw> operaPswList = initOperaPsw(brandId);
            for (OperaPsw psw : operaPswList) {
                if (Objects.equals(psw.getModule(), module)) {
                    return psw;
                }
            }
        }
        return operaPsw;
    }

    /**
     * 初始化操作密钥
     */
    private List<OperaPsw> initOperaPsw(Integer brandId) {
        List<OperaPsw> operaPswList = new ArrayList<>();
        OperaPsw operaPsw;
        for (OperaPswEnum item : OperaPswEnum.values()) {
            operaPsw = new OperaPsw();
            operaPsw.setBrandId(brandId);
            operaPsw.setModuleName(item.getModuleName());
            operaPsw.setModule(item.getModule());
            operaPsw.setOperaPsw(item.getOperaPsw());
            operaPsw.setEnable(1);
            operaPsw.setOperaUserId(0);
            operaPsw.setCreateTime(new Date());
            operaPsw.setUpdateTime(new Date());
            operaPswList.add(operaPsw);
        }
        operaPswDao.batchInsert(operaPswList);
        return operaPswList;
    }
}
